An inherited member function can be hidden in a derived class and that creates a class that behaves differently depending on which
interface is used to manipulate it.
Overriding happens when the inherited method is virtual and a method declared in the derived class uses the same identifier as well as the same
signature (the return types can be different, as long as they are covariant). However, if the inherited method is non-virtual
or if the two declarations of the method do not share the same signature, the method of the base class will be hidden.
Such a class increases the inheritance complexity and confuses consumers with its non-polymorphic behavior, which can lead to errors.
Noncompliant code example
class Base {
public:
void shutdown();
virtual void log(int a);
};
class Derived : public Base {
public:
void shutdown(); //Noncompliant
void log(float a); //Noncompliant
};
void stopServer(Base *obj, Derived *obj2) {
obj->shutdown(); // always calls Base::shutdown even if the given object's type is Derived
obj->log(2); // calls Base::log(int) even if the given object's type is Derived
obj2->shutdown(); // calls Derived::shutdown
obj2->log(2); // calls Derived::log(float), even if this requires a conversion int->float.
}
Compliant solution
class Base {
public:
void shutdown();
virtual void log(int a);
};
class Derived : public Base {
public:
void shutdownAndUpdate(); // Define a method with a different name
void log(int a) override; // Or make the method a proper override
};
void stopServer(Base *obj) {
obj->shutdown(); // calls Base::shutdown and there is no confusion
obj->log(2); // calls Derived::log(int) if the given object's type is Derived
}